package jp.sourceforge.akjrcp.ui.param;

import jp.sourceforge.akjrcp.ui.param.AbstractParamCompositeItem.SelectionCheck;
import jp.sourceforge.akjrcp.util.TimeUtils;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;

public class ParamTime extends AbstractParamCompositeItem{

private String key;
private String label;

private Label labelItem;

private Label hourLabel;
private Label minuteLabel;
private Label secondLabel;
private Label millisecondLabel;

private String value="";

private Spinner hourSpinner;
private Spinner minuteSpinner;
private Spinner secondSpinner;
private Spinner millisecondSpinner;

public String getKey() {
	return key;
}




public void setToolTipText(String text){
	if(hourLabel!=null)hourLabel.setToolTipText(text);
	if(minuteLabel!=null)minuteLabel.setToolTipText(text);
	if(secondLabel!=null)secondLabel.setToolTipText(text);
	if(millisecondLabel!=null)millisecondLabel.setToolTipText(text);
	
	if(hourSpinner!=null)hourSpinner.setToolTipText(text);
	if(minuteSpinner!=null)minuteSpinner.setToolTipText(text);
	if(secondSpinner!=null)secondSpinner.setToolTipText(text);
	if(millisecondSpinner!=null)millisecondSpinner.setToolTipText(text);
}

/**
 * 
 * @return selection millisecond
 */
public long getTime(){
	long value=0;
	if(hourSpinner!=null){
		value+=hourSpinner.getSelection()*60*60*1000;
	}
	
	if(minuteSpinner!=null){
		value+=minuteSpinner.getSelection()*60*1000;
	}
	
	if(secondSpinner!=null){
		value+=secondSpinner.getSelection()*1000;
	}
	
	if(millisecondSpinner!=null){
		value+=millisecondSpinner.getSelection();
	}
	
	return value;
}

/**
 * @return 00:00:00.000 
 */
public String getValue() {
	return TimeUtils.toTimeText(getTime());
}

public void addModifyListener(ModifyListener listener) {
	if(hourSpinner!=null)
	hourSpinner.addModifyListener(listener);
	if(minuteSpinner!=null)
	minuteSpinner.addModifyListener(listener);
	if(secondSpinner!=null)
	secondSpinner.addModifyListener(listener);
	if(millisecondSpinner!=null)
	millisecondSpinner.addModifyListener(listener);
}

public void addSelectionListener(SelectionListener listener) {
			if(hourSpinner!=null)
			hourSpinner.addSelectionListener(listener);
			if(minuteSpinner!=null)
			minuteSpinner.addSelectionListener(listener);
			if(secondSpinner!=null)
			secondSpinner.addSelectionListener(listener);
			if(millisecondSpinner!=null)
			millisecondSpinner.addSelectionListener(listener);
}

public void removeSelectionListener(SelectionListener listener) {
	if(hourSpinner!=null)
	hourSpinner.removeSelectionListener(listener);
	if(minuteSpinner!=null)
	minuteSpinner.removeSelectionListener(listener);
	if(secondSpinner!=null)
	secondSpinner.removeSelectionListener(listener);
	if(millisecondSpinner!=null)
	millisecondSpinner.removeSelectionListener(listener);
}

public void setValue(String value) {
	if(value.length()>0){//set valid value
		int[] vs=TimeUtils.toHourMinSecMilliSecond(value);
		if(vs!=null){
			if(hourSpinner!=null)
			hourSpinner.setSelection(vs[0]);
			if(minuteSpinner!=null)
			minuteSpinner.setSelection(vs[1]);
			if(secondSpinner!=null)
			secondSpinner.setSelection(vs[2]);
			if(millisecondSpinner!=null)
			millisecondSpinner.setSelection(vs[3]);
		}
	}
	this.value=value;
}
/**
 * 999:59:59.999
 * @param parent
 * @param style only READ_ONLY WORK and setEnabled(false) is good for effect.
 * @param key
 * @param label
 */
public ParamTime(Composite parent, int style,String key,String label){
	this(parent,style,key,label,true,true,true,true);
}
	public ParamTime(Composite parent, int style,String key,String label,boolean showHour,boolean showMinute,boolean showSecond,boolean showMilliSecond) {
		super(parent, style);
		
		this.key=key;
		this.label=label;
		
		this.setLayout(new GridLayout(2,false));
		labelItem = new Label(this,SWT.NONE);
		labelItem.setText(label);
		
		int count=0;
		if(showHour){
			count+=2;
		}
		if(showMinute){
			count+=2;
		}
		if(showSecond){
			count+=2;
		}
		if(showMilliSecond){
			count+=2;
		}
		Composite spinnergroup=new Composite(this,SWT.NULL);
		spinnergroup.setLayout(new GridLayout(count,false));
		if(showHour){
			hourSpinner= new Spinner(spinnergroup,style&SWT.READ_ONLY);
			hourSpinner.setMaximum(999);//TODO change?
			hourSpinner.addSelectionListener(new SelectionCheck());
			hourLabel=new Label(spinnergroup,SWT.NONE);
			hourLabel.setText(":");
			
			new SpinnerLoopSupport(hourSpinner);
		}
		if(showMinute){
			minuteSpinner= new Spinner(spinnergroup,style&SWT.READ_ONLY);
			minuteSpinner.setMaximum(59);
			minuteSpinner.addSelectionListener(new SelectionCheck());
			minuteLabel=new Label(spinnergroup,SWT.NONE);
			minuteLabel.setText(":");
			
			new SpinnerLoopSupport(minuteSpinner);
		}
		if(showSecond){
			secondSpinner= new Spinner(spinnergroup,style&SWT.READ_ONLY);
			secondSpinner.setMaximum(59);
			secondSpinner.addSelectionListener(new SelectionCheck());
			secondLabel=new Label(spinnergroup,SWT.NONE);
			if(showMilliSecond){
			secondLabel.setText(".");
			}else{
			secondLabel.setText("");
			}
			new SpinnerLoopSupport(secondSpinner);
		}
		if(showMilliSecond){
			millisecondSpinner= new Spinner(spinnergroup,style&SWT.READ_ONLY);
			millisecondSpinner.setMaximum(999);
			
			millisecondLabel=new Label(spinnergroup,SWT.NONE);
			millisecondLabel.setText("");
			millisecondSpinner.addSelectionListener(new SelectionCheck());
			

			
			new SpinnerLoopSupport(millisecondSpinner);
			
		}
		//GridData gdata=new GridData();
		//gdata.widthHint=30;
		
		//spinnerAndScale.setLayoutData(gdata);
	}

	/*
	 * when value is minumum and click down ,value change to maximum.and same as up click
	 */
	public static class SpinnerLoopSupport implements MouseListener,SelectionListener,ModifyListener{
		private Spinner spinner;
		private long last;
		private int areaX=7; //0-9
		//private boolean canChange;
		public SpinnerLoopSupport(Spinner spinner){
			this.spinner=spinner;
		
		
			spinner.addMouseListener(this);
			spinner.addSelectionListener(this);
			spinner.addModifyListener(this);
			if(spinner.getMaximum()>9){
				areaX=13;
			}
			if(spinner.getMaximum()>99){
				areaX=20;
			}
			if(spinner.getMaximum()>999){//guess
				areaX=27;
			}
		}
			
			public void mouseDoubleClick(MouseEvent e) {
				// TODO Auto-generated method stub
				
			}

			public void mouseDown(MouseEvent e) {
				//log.infomousedown");
				//canChange=true;
				//last=System.currentTimeMillis();
			}

			//* hope called after widgetSelected()
			public void mouseUp(MouseEvent e) {
				//log.infomouseup");
				if(System.currentTimeMillis()-last<750){//modified
					return;
				}
				
				if(e.x>areaX){
					if(e.y<8){
						if(spinner.getSelection()==spinner.getMaximum()){
							spinner.setSelection(spinner.getMinimum());
						}
						
					}else if(e.y>8){
						if(spinner.getSelection()==spinner.getMinimum()){
							spinner.setSelection(spinner.getMaximum());
						}
					}
				}
			}

			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub
				
			}

			public void widgetSelected(SelectionEvent e) {
				//log.infoselected");
				//log.info(e);
				last=System.currentTimeMillis();
			}

			public void modifyText(ModifyEvent e) {
				last=System.currentTimeMillis();
				//log.infomodified");
				//canChange=false;
			}
		
		
	}

	
	public boolean isModified() {
		
		String oldValue=getValue();
		
		
		
		return !oldValue.equals(value);
	}







	public String getLabel() {
		return label;
	}




	public void setLabel(String label) {
		this.label = label;
	}


}
